home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Arsenal Files 8
/
The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO
/
g_duke
/
mapprt.zip
/
MAP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-18
|
18KB
|
705 lines
/*
MAP.C
Oliver Kraus
kraus@lrs.e-technik.uni-erlangen.de
*/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "map.h"
#include "names.h"
#define MAP_NONE 0
#define MAP_ASSAULT_TROOPER 1
#define MAP_ASSAULT_CAPTAIN 2
#define MAP_PIC_COP 3
#define MAP_RECON_PATROL 4
#define MAP_OCTABRAIN 5
#define MAP_ENFORCER 6
#define MAP_SENTRY_DRONE 7
#define MAP_ASSAULT_COMMANDER 8
#define MAP_PROTOZOID_SLIMER 9
#define MAP_BATTLELORD 10
#define MAP_OVERLORD 11
#define MAP_CYCLOID_EMPEROR 12
#define MAP_TURRET 13
#define MAP_EGG 14
#define MAP_ROTATE_GUN 15 /* same as MAP_TURRET? */
#define MAP_BLUE_CARD 100
#define MAP_RED_CARD 101
#define MAP_YELLOW_CARD 102
#define MAP_EXIT 200
#define MAP_BONUS_EXIT 201
struct _map_sprite_to_item
{
short picnum;
short palette;
short item;
};
typedef struct _map_sprite_to_item map_sprite_to_item;
struct _map_item_info_struct
{
short typ;
short item;
long cnt;
char *id;
char *name;
char *altname;
};
typedef struct _map_item_info_struct map_item_info_struct;
map_item_info_struct map_item_info[] =
{
{ 0 , MAP_NONE , 0L, "??", "unknown" , NULL },
{ MAP_TYP_MONSTER, MAP_ASSAULT_CAPTAIN , 0L, "AC", "Assault Captain" , "Lizman" },
{ MAP_TYP_MONSTER, MAP_ASSAULT_COMMANDER , 0L, "AM", "Assault Commander" , NULL },
{ MAP_TYP_MONSTER, MAP_ASSAULT_TROOPER , 0L, "AT", "Assault Trooper" , "Liztroop" },
{ MAP_TYP_MONSTER, MAP_BATTLELORD , 0L, "BL", "Battlelord" , "Boss 1" },
{ MAP_TYP_MONSTER, MAP_CYCLOID_EMPEROR , 0L, "CE", "Cycloid Emperor" , "Boss 3" },
{ MAP_TYP_MONSTER, MAP_EGG , 0L, "EG", "Egg" , NULL },
{ MAP_TYP_MONSTER, MAP_ENFORCER , 0L, "EN", "Enforcer" , "Mini Boss 1" },
{ MAP_TYP_MONSTER, MAP_OCTABRAIN , 0L, "OB", "Octabrain" , NULL },
{ MAP_TYP_MONSTER, MAP_OVERLORD , 0L, "OL", "Overlord" , "Boss 2" },
{ MAP_TYP_MONSTER, MAP_PIC_COP , 0L, "PC", "Pic Cop" , NULL },
{ MAP_TYP_MONSTER, MAP_PROTOZOID_SLIMER , 0L, "PS", "Protozoid Slimer" , NULL },
{ MAP_TYP_MONSTER, MAP_ROTATE_GUN , 0L, "RG", "Rotate Gun" , NULL },
{ MAP_TYP_MONSTER, MAP_RECON_PATROL , 0L, "RP", "Recon Patrol Car" , NULL },
{ MAP_TYP_MONSTER, MAP_SENTRY_DRONE , 0L, "SD", "Sentry Drone" , NULL },
{ MAP_TYP_MONSTER, MAP_TURRET , 0L, "TU", "Turret" , NULL },
{ MAP_TYP_CARD, MAP_BLUE_CARD , 0L, "BC", "Blue Card" , NULL },
{ MAP_TYP_CARD, MAP_RED_CARD , 0L, "RC", "Red Card" , NULL },
{ MAP_TYP_CARD, MAP_YELLOW_CARD , 0L, "YC", "Yellow Card" , NULL },
{ -1 , MAP_NONE , 0L, NULL, NULL }
};
char *map_get_item_id(int idx)
{
if ( idx < 0 )
return "";
return map_item_info[idx].id;
}
char *map_get_item_string(int idx)
{
if ( idx < 0 )
return "";
return map_item_info[idx].name;
}
int map_get_item_typ(int idx)
{
if ( idx < 0 )
return 0;
return (int)map_item_info[idx].typ;
}
int map_get_item_cnt(int idx)
{
if ( idx < 0 )
return 0;
return (int)map_item_info[idx].cnt;
}
map_sprite_to_item map_to_item[] =
{
{ LIZTROOP , -1, MAP_ASSAULT_TROOPER },
{ LIZTROOPRUNNING , -1, MAP_ASSAULT_TROOPER },
{ LIZTROOPSTAYPUT , -1, MAP_ASSAULT_TROOPER },
{ LIZTOP , -1, MAP_ASSAULT_TROOPER },
{ LIZTROOPSHOOT , -1, MAP_ASSAULT_TROOPER },
{ LIZTROOPJETPACK , -1, MAP_ASSAULT_TROOPER },
{ LIZTROOPDSPRITE , -1, MAP_ASSAULT_TROOPER },
{ LIZTROOPONTOILET , -1, MAP_ASSAULT_TROOPER },
{ LIZTROOPDUCKING , -1, MAP_ASSAULT_TROOPER },
{ OCTABRAIN , -1, MAP_OCTABRAIN },
{ OCTABRAINSTAYPUT , -1, MAP_OCTABRAIN },
{ OCTATOP , -1, MAP_OCTABRAIN },
{ DRONE , -1, MAP_SENTRY_DRONE },
{ COMMANDER , -1, MAP_ASSAULT_COMMANDER },
{ COMMANDERSTAYPUT , -1, MAP_ASSAULT_COMMANDER },
{ RECON , -1, MAP_RECON_PATROL },
{ PIGCOP , -1, MAP_PIC_COP },
{ PIGCOPSTAYPUT , -1, MAP_PIC_COP },
{ PIGCOPDIVE , -1, MAP_PIC_COP },
{ PIGTOP , -1, MAP_PIC_COP },
{ LIZMAN , -1, MAP_ASSAULT_CAPTAIN },
{ LIZMANSTAYPUT , -1, MAP_ASSAULT_CAPTAIN },
{ LIZMANSPITTING , -1, MAP_ASSAULT_CAPTAIN },
{ LIZMANFEEDING , -1, MAP_ASSAULT_CAPTAIN },
{ LIZMANJUMP , -1, MAP_ASSAULT_CAPTAIN },
{ BOSS1 , -1, MAP_BATTLELORD },
{ BOSS1STAYPUT , -1, MAP_BATTLELORD },
{ BOSS1SHOOT , -1, MAP_BATTLELORD },
{ BOSS1LOB , -1, MAP_BATTLELORD },
{ BOSSTOP , -1, MAP_BATTLELORD },
{ BOSS3 , -1, MAP_OVERLORD }, /* strange BOSS2/BOSS3 */
{ BOSS2 , -1, MAP_CYCLOID_EMPEROR },
{ EGG , -1, MAP_EGG },
{ ROTATEGUN , -1, MAP_ROTATE_GUN },
{ ACCESSCARD , 0, MAP_BLUE_CARD },
{ ACCESSCARD , 21, MAP_RED_CARD },
{ ACCESSCARD , 23, MAP_YELLOW_CARD },
{ -1, -1, -1}
};
int map_get_info_idx(short picnum, short palette)
{
int i, j;
i = 0;
while ( map_to_item[i].item >= 0 )
{
if ( map_to_item[i].picnum == picnum )
{
if ( map_to_item[i].palette < 0 )
break;
if ( map_to_item[i].palette == palette )
break;
}
i++;
}
if ( map_to_item[i].item < 0 )
return -1;
j = 0;
while ( map_item_info[j].typ >= 0 )
{
if ( map_item_info[j].item == map_to_item[i].item )
break;
j++;
}
if ( map_item_info[j].typ < 0 )
return -1;
return j;
}
int is_map_file(char *name)
{
long lval, pos;
short sval;
map_player_struct pl;
FILE *fp;
pos = 0L;
fp = fopen(name, "rb");
if ( fp == NULL )
return 0;
if ( fread(&lval, sizeof(long), 1, fp) != 1 )
{
fclose(fp);
return 0;
}
pos += sizeof(long);
/* check version number */
if ( lval < 7 )
{
fclose(fp);
return 0;
}
if ( lval > 100 )
{
fclose(fp);
return 0;
}
if ( fread(&pl, sizeof(map_player_struct), 1, fp) != 1 )
{
fclose(fp);
return 0;
}
if ( pl.ang >= 2048 )
{
fclose(fp);
return 0;
}
pos += sizeof(map_player_struct);
if ( fread(&sval, sizeof(short), 1, fp) != 1 )
{
fclose(fp);
return 0;
}
if ( sval < 0 )
{
fclose(fp);
return 0;
}
pos += (long)sizeof(short);
pos += (long)sizeof(map_sector_struct)*(long)sval;
if ( fseek(fp, pos, SEEK_SET) != 0 )
{
fclose(fp);
return 0;
}
if ( ftell(fp) != pos )
{
fclose(fp);
return 0;
}
if ( fread(&sval, sizeof(short), 1, fp) != 1 )
{
fclose(fp);
return 0;
}
if ( sval < 0 )
{
fclose(fp);
return 0;
}
pos += (long)sizeof(short);
pos += (long)sizeof(map_wall_struct)*(long)sval;
if ( fseek(fp, pos, SEEK_SET) != 0 )
{
fclose(fp);
return 0;
}
if ( ftell(fp) != pos )
{
fclose(fp);
return 0;
}
if ( fread(&sval, sizeof(short), 1, fp) != 1 )
{
fclose(fp);
return 0;
}
if ( sval < 0 )
{
fclose(fp);
return 0;
}
pos += (long)sizeof(short);
pos += (long)sizeof(map_sprite_struct)*(long)sval;
if ( fseek(fp, pos, SEEK_SET) != 0 )
{
fclose(fp);
return 0;
}
if ( ftell(fp) != pos )
{
fclose(fp);
return 0;
}
if ( fgetc(fp) != EOF )
{
fclose(fp);
return 0;
}
fclose(fp);
return 1;
}
void map_name_cut(char *s)
{
size_t i = 0;
while( s[i] != '\0' )
{
if ( s[i] == '.' )
{
s[i] = '\0';
break;
}
i++;
}
}
int map_name_split(char *dest, long *val, char *src)
{
size_t len, i;
len = strlen(src);
i = len;
while( i > 0 )
{
i--;
if ( !isdigit(src[i]) )
{
i++;
break;
}
}
strncpy(dest, src, i);
dest[i] = '\0';
if ( i == len )
return 0;
*val = atol(src+i);
return 1;
}
int map_name_compare(char *n1, char *n2)
{
int ret, r1, r2;
long v1, v2;
static char s1[14];
static char s2[14];
static char t1[14];
static char t2[14];
strncpy(t1, n1, 12);
strncpy(t2, n2, 12);
t1[12] = '\0';
t2[12] = '\0';
map_name_cut(t1);
map_name_cut(t2);
r1 = map_name_split(s1, &v1, t1);
r2 = map_name_split(s2, &v2, t2);
if ( r1 != 0 && r2 != 0 )
{
ret = strcmp(s1, s2);
if ( ret == 0 )
{
if ( v1 < v2 )
ret = -1;
else if ( v1 > v2 )
ret = 1;
}
}
else
{
ret = strcmp(t1, t2);
}
return ret;
}
/*
if 'fp' is NULL, a filepointer is generated with
fopen and fname
*/
map_type map_Open(char *fname, FILE *fp)
{
map_type map;
int is_close_fp = 0;
if ( fname == NULL )
return NULL;
if ( fp == NULL )
{
fp = fopen(fname, "rb");
if ( fp == NULL )
return NULL;
is_close_fp = 1;
}
map = (map_type)malloc(sizeof(map_struct));
if ( map != NULL )
{
map->fname = (char *)malloc(strlen(fname)+1);
if ( map->fname != NULL )
{
strcpy(map->fname, fname);
map->is_close_fp = is_close_fp;
map->fp = fp;
map->sec_list = NULL;
map->wall_list = NULL;
map->sprite_list = NULL;
map_SetMonster(map);
map_SetCard(map);
return map;
}
free(map);
}
if ( is_close_fp != 0 )
fclose(fp);
return NULL;
}
void map_Close(map_type map)
{
if ( map != NULL )
{
if ( map->sec_list != NULL )
free(map->sec_list);
if ( map->wall_list != NULL )
free(map->wall_list);
if ( map->sprite_list != NULL )
free(map->sprite_list);
if ( map->is_close_fp != 0 )
fclose(map->fp);
free(map->fname);
free(map);
}
}
short map_GetShort(map_type map)
{
short x;
if ( fread(&x, sizeof(short), 1, map->fp) != 1 )
{
perror("read 16 Bit");
return -1;
}
return x;
}
int map_read_version(map_type map)
{
char *task = "read version";
if ( fread(&(map->version), sizeof(long), 1, map->fp) != 1 )
{
perror(task);
return 0;
}
return 1;
}
int map_read_player_pos(map_type map)
{
char *task = "read player pos";
if ( fread(&(map->player), sizeof(map_player_struct), 1, map->fp) != 1 )
{
perror(task);
return 0;
}
return 1;
}
int map_read_sector_list(map_type map)
{
char *task = "read sector list";
map->sec_cnt = map_GetShort(map);
if ( map->sec_cnt < 0 )
return 0;
if ( map->sec_list != NULL )
free(map->sec_list);
map->sec_list = (map_sector_struct *)
malloc(sizeof(map_sector_struct)*(size_t)map->sec_cnt);
if ( map->sec_list == NULL )
{
fprintf( map->fp, "%s: out of memory\n", task);
return 0;
}
if ( fread((void *)(map->sec_list),
sizeof(map_sector_struct),
(size_t)map->sec_cnt, map->fp) != map->sec_cnt )
{
perror(task);
return 0;
}
return 1;
}
int map_read_wall_list(map_type map)
{
char *task = "read wall list";
map->wall_cnt = map_GetShort(map);
if ( map->wall_cnt < 0 )
return 0;
if ( map->wall_list != NULL )
free(map->wall_list);
map->wall_list = (map_wall_struct *)
malloc(sizeof(map_wall_struct)*(size_t)map->wall_cnt);
if ( map->wall_list == NULL )
{
fprintf( map->fp, "%s: out of memory\n", task);
return 0;
}
if ( fread((void *)(map->wall_list),
sizeof(map_wall_struct),
(size_t)map->wall_cnt, map->fp) != map->wall_cnt )
{
perror(task);
return 0;
}
return 1;
}
int map_read_sprite_list(map_type map)
{
char *task = "read sprite list";
map->sprite_cnt = map_GetShort(map);
if ( map->sprite_cnt < 0 )
return 0;
if ( map->sprite_list != NULL )
free(map->sprite_list);
map->sprite_list = (map_sprite_struct *)
malloc(sizeof(map_sprite_struct)*(size_t)map->sprite_cnt);
if ( map->sprite_list == NULL )
{
fprintf( map->fp, "%s: out of memory\n", task);
return 0;
}
if ( fread((void *)(map->sprite_list),
sizeof(map_sprite_struct),
(size_t)map->sprite_cnt, map->fp) != map->sprite_cnt )
{
perror(task);
return 0;
}
return 1;
}
int map_Read(map_type map, long pos)
{
if ( fseek(map->fp, pos, SEEK_SET) != 0 )
{
perror("file seek");
return 0;
}
if ( map_read_version(map) == 0 )
return 0;
if ( map_read_player_pos(map) == 0 )
return 0;
if ( map_read_sector_list(map) == 0 )
return 0;
if ( map_read_wall_list(map) == 0 )
return 0;
if ( map_read_sprite_list(map) == 0 )
return 0;
return 1;
}
/* calculate the size of the map, ignoring texture 0 walls */
int map_CalculateSize(map_type map)
{
short i, j;
short wallnum, wallidx;
long x, y;
map->min_x = 0x07fffffffL;
map->min_y = 0x07fffffffL;
map->max_x = -0x07fffffffL;
map->max_y = -0x07fffffffL;
for( i = 0; i < map->sec_cnt; i++ )
{
wallnum = map->sec_list[i].wallnum;
wallidx = map->sec_list[i].wallptr;
if (
map->sec_list[i].ceilingstat != 0 ||
map->sec_list[i].floorstat != 0 ||
map->sec_list[i].ceilingshade != 0 ||
map->sec_list[i].ceilingpal != 0 ||
map->sec_list[i].ceilingxpanning != 0 ||
map->sec_list[i].ceilingypanning != 0 ||
map->sec_list[i].floorshade != 0 ||
map->sec_list[i].floorpal != 0 ||
map->sec_list[i].floorxpanning != 0 ||
map->sec_list[i].floorypanning != 0 ||
map->sec_list[i].visibility != 0 ||
map->sec_list[i].filler != 0 ||
map->sec_list[i].lotag != 0 ||
map->sec_list[i].hitag != 0
)
{
for( j = 0; j < wallnum; j++ )
{
x = map->wall_list[wallidx].x;
y = map->wall_list[wallidx].y;
/* NOTE: To ignore logos on the map, art with idx 0 is ignored */
/* hopeing, that nobody assigns textures to his logo */
/* well... wrong see e3l2.map of duke3d: checking more stuff */
if ( map->wall_list[wallidx].picnum != 0 )
{
if ( map->min_x > x )
map->min_x = x;
if ( map->min_y > y )
map->min_y = y;
if ( map->max_x < x )
map->max_x = x;
if ( map->max_y < y )
map->max_y = y;
}
wallidx = map->wall_list[wallidx].point2;
}
}
}
/*
for( i = 0; i < map->wall_cnt; i++ )
{
if ( map->min_x > map->wall_list[i].x )
map->min_x = map->wall_list[i].x;
if ( map->min_y > map->wall_list[i].y )
map->min_y = map->wall_list[i].y;
if ( map->max_x < map->wall_list[i].x )
map->max_x = map->wall_list[i].x;
if ( map->max_y < map->wall_list[i].y )
map->max_y = map->wall_list[i].y;
}
*/
return 1;
}
int map_cnt_sprites(map_type map)
{
int j;
int idx;
map_sprite_struct *sprite;
short i;
j = 0;
while ( map_item_info[j].typ >= 0 )
{
map_item_info[j].cnt = 0L;
j++;
}
for( i = 0; i < map->sprite_cnt; i++ )
{
sprite = map->sprite_list+i;
idx = map_get_info_idx(sprite->picnum, sprite->pal);
if ( idx >= 0 )
{
if ( map_get_item_typ(idx) == MAP_TYP_MONSTER &&
map->is_monster == 0 )
continue;
if ( map_get_item_typ(idx) == MAP_TYP_CARD &&
map->is_card == 0 )
continue;
map_item_info[idx].cnt++;
}
}
map->legend_item_cnt = 0;
j = 0;
while ( map_item_info[j].typ >= 0 )
{
if ( map_item_info[j].cnt != 0L )
map->legend_item_cnt++;
j++;
}
return map->legend_item_cnt;
}